#ifndef _HELIX_TEST_SUITE_H_
#define _HELIX_TEST_SUITE_H_

// MyTestSuite.h
#include <cxxtest/TestSuite.h>
//#include <stdio.h>
#include "../Helix/Log.h"
#include "../Helix/HObject.h"
//#include "Helix/HXMLUtil.h"
#include "../Helix/LinkedList.h"
#include "../Helix/Util/pointerCheck.h"
#include "../Helix/Math/Vector.h"

using namespace helix;

class LogTest : public CxxTest::TestSuite
{
public:
	void testLogCreation( void )
	{
		Log *tLog=new Log("testlog.txt");
		delete tLog;
		FILE *file=fopen("testlog.txt","r");
		TS_ASSERT( file!=NULL );
		fclose(file);
	}

};

class pointerCheckTest : public CxxTest::TestSuite
{
public:

	void testPtrCheck( void )
	{
		HObject *obj=new HObject();

		bool ptrValid=PtrCheck::isValid(obj);
		TS_ASSERT(ptrValid);

		delete obj;
		ptrValid=PtrCheck::isValid(obj);
		TS_ASSERT(!(PtrCheck::isValid(obj)));
	}

	void testSafeDelete(void)
	{
		HObject *obj=new HObject();
		bool deleted=true;
		TS_ASSERT(PtrCheck::safeDelete(obj,"Object:"));
		TS_ASSERT(!PtrCheck::safeDelete(obj,"Object:"));
		TS_ASSERT(!PtrCheck::safeDelete(obj,"Object:"));
	}
};

class HObjectTest : public CxxTest::TestSuite
{
public:
	void testRefs( void )
	{
		printf("\n\nHObjectTest::testRefs\n");
		HObject *obj=new HObject();
		obj->AddRef();
		TS_ASSERT_EQUALS(obj->GetRefCount(), 1 );
		obj->DeleteRef();
		TS_ASSERT_EQUALS(obj->GetRefCount(), 0 );
		delete obj;
	}
};

class LinkedListTest : public CxxTest::TestSuite
{
public:
	HObject *obj;
	HObject *obj2;
	HObject *obj3;
	HObject *obj4;
	void setUp()
	{
		printf("\n\nHLinkedListTest::");
		obj=new HObject();
		obj2=new HObject();
		obj3=new HObject();
		obj4=new HObject();
	}

	void tearDown()
	{
		/*if(PtrCheck::isValid(obj))
			delete obj;
		if(PtrCheck::isValid(obj2))
			delete obj2;
		if(PtrCheck::isValid(obj3))
			delete obj3;
		*/
		PtrCheck::safeDelete(obj,"Object 1");
		PtrCheck::safeDelete(obj2,"Object 2");
		PtrCheck::safeDelete(obj3,"Object 3");
		PtrCheck::safeDelete(obj4,"Object 4");
	}

	void testAddFirst( void )
	{
		printf("testAddFirst\n");
		LinkedList *list=new LinkedList();
		list->AddFirst(obj);
		TS_ASSERT_EQUALS(list->First(),obj);
		list->AddFirst(obj2);
		TS_ASSERT_EQUALS(list->First(),obj2);
		list->AddFirst(obj3);
		TS_ASSERT_EQUALS(list->First(),obj3);
		delete list;
	}

	void testAddLast(void)
	{
		printf("testAddLast\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		TS_ASSERT_EQUALS(list->First(),obj);
		TS_ASSERT_EQUALS(list->Next(),obj2);
		TS_ASSERT_EQUALS(list->Next(),obj3);
		delete list;
	}

	void testAddMiddle(void)
	{
		printf("testAddMiddle\n");
		LinkedList *list=new LinkedList();
		list->AddMiddle(obj,0);
		list->AddMiddle(obj2,1);
		list->AddMiddle(obj3,1);
		list->AddMiddle(obj4,2);
		TS_ASSERT_EQUALS(list->First(),obj);
		TS_ASSERT_EQUALS(list->Next(),obj3);
		TS_ASSERT_EQUALS(list->Next(),obj4);
		TS_ASSERT_EQUALS(list->Next(),obj2);
		delete list;
	}

	void testRemoveFirst(void)
	{
		printf("testRemoveFirst\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->First();
		list->Remove();
		TS_ASSERT_EQUALS(list->First(),obj2);
		TS_ASSERT_EQUALS(list->Next(),obj3);
		TS_ASSERT_EQUALS(list->Next(),obj4);
		TS_ASSERT_EQUALS(list->Length(),3);
		delete obj;
		delete list;
	}

	void testRemoveLast(void)
	{
		printf("testRemoveLast\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->Remove();
		TS_ASSERT_EQUALS(list->First(),obj);
		TS_ASSERT_EQUALS(list->Next(),obj2);
		TS_ASSERT_EQUALS(list->Next(),obj3);
		TS_ASSERT_EQUALS(list->Length(),3);
		delete obj4;
		delete list;
	}

	void testRemoveMiddle(void)
	{
		printf("testRemoveMiddle\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->First();
		list->Next();
		list->Remove();
		TS_ASSERT_EQUALS(list->First(),obj);
		TS_ASSERT_EQUALS(list->Next(),obj3);
		TS_ASSERT_EQUALS(list->Next(),obj4);
		TS_ASSERT_EQUALS(list->Length(),3);
		delete obj2;
		delete list;
	}

	void testRemoveObjectFirst(void)
	{
		printf("testRemoveObjectFirst\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->Remove(obj);
		TS_ASSERT_EQUALS(list->First(),obj2);
		TS_ASSERT_EQUALS(list->Next(),obj3);
		TS_ASSERT_EQUALS(list->Next(),obj4);
		TS_ASSERT_EQUALS(list->Length(),3);
		delete obj;
		delete list;
	}

	void testRemoveObjectLast(void)
	{
		printf("testRemoveObjectLast\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->Remove(obj4);
		TS_ASSERT_EQUALS(list->First(),obj);
		TS_ASSERT_EQUALS(list->Next(),obj2);
		TS_ASSERT_EQUALS(list->Next(),obj3);
		TS_ASSERT_EQUALS(list->Length(),3);
		delete obj4;
		delete list;
	}

	void testRemoveObjectMiddle(void)
	{
		printf("testRemoveObjectMiddle\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->Remove(obj3);
		TS_ASSERT_EQUALS(list->First(),obj);
		TS_ASSERT_EQUALS(list->Next(),obj2);
		TS_ASSERT_EQUALS(list->Next(),obj4);
		TS_ASSERT_EQUALS(list->Length(),3);
		delete obj3;
		delete list;
	}

	void testGetObject(void)
	{
		printf("testGetObject\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->First();
		list->Next();

		TS_ASSERT_EQUALS(list->GetObj(),obj2);
		delete list;
	}

	void testGetObjectAtIndex(void)
	{
		printf("testGetObjectAtIndex\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->First();
		list->Next();
		list->Next();	//go one past the object we want, just to be sure it works

		TS_ASSERT_EQUALS(list->GetObj(1),obj2);
		delete list;
	}

	void testDelete(void)
	{
		printf("testDelete\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->First();
		list->Delete();
		obj2->AddRef();
		list->Delete();

		TS_ASSERT(!PtrCheck::isValid(obj));
		TS_ASSERT(PtrCheck::isValid(obj2));
		delete obj2;
		delete list;
	}

	void testDeleteIndex(void)
	{
		printf("testDeleteIndex\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->Delete(2);
		obj2->AddRef();
		list->Delete(1);

		TS_ASSERT(!PtrCheck::isValid(obj3));
		TS_ASSERT(PtrCheck::isValid(obj2));
		delete obj2;
		delete list;
	}

	void testDeleteObject(void)
	{
		printf("testDeleteObject\n");
		LinkedList *list=new LinkedList();
		list->AddLast(obj);
		list->AddLast(obj2);
		list->AddLast(obj3);
		list->AddLast(obj4);
		list->Delete(obj3);
		obj2->AddRef();
		list->Delete(obj2);

		TS_ASSERT(!PtrCheck::isValid(obj3));
		TS_ASSERT(PtrCheck::isValid(obj2));
		delete obj2;
		delete list;
	}
};


#endif
